<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:job="livcos.org/ns/process/job"
  xmlns:c="livcos.org/ns/cosmos"
  xmlns:doc="livcos.org/ns/doc"
  xmlns:u="livcos.org/ns/cosmos/update"
  xmlns:m="livcos.org/ns/map"
  xmlns:cb="livcos.org/ns/clipboard"
  xmlns:f="livcos.org/ns/xslt/function"
  xmlns="livcos.org/ns/map"
  exclude-result-prefixes="c job u m f doc cb">
  
  <xsl:import href="../../web/editor/clipboard/Edit.xsl"/>
  
	<xsl:variable name="integrityCheckObjId" select="'/livcos.org/Map/web/integrity'"/>
	
	<xsl:template match="/">
		<xsl:apply-templates select="*/c:request/parameter/*"/>
		<job:feed ref="{$view}" stream="response" base="job"/>
		<!-- TODO: interpret simple, small JSON edit feedback to merge changes in client JavaScript -->
		<!--job:feed ref="{substring-before($viewObjId,'edit_clipboard')}edit_feedback.view" stream="response" base="job"
			content-type="text/plain"/-->
	</xsl:template>
  
  <xsl:template match="m:item" mode="paste">
  	<!-- paste item -->
  	<u:insert select="..">
      <item id="{@id}">
        <xsl:copy-of select="m:label | doc:*" copy-namespaces="no"/>
      	<xsl:apply-templates select="m:rels" mode="insert"/>
				<xsl:if test="not(m:rels[@group = 'sys'])">
					<rels id="{{new-id()}}" group="sys">
						<rel id="{{new-id()}}" ref="#{$id}"/>
					</rels>
				</xsl:if>
      </item>
  	</u:insert>
  	<!-- correct/copy backward relations -->
  	<xsl:apply-templates select="m:rels/m:rel" mode="backRef"/>
  	<!-- relate this item to the pasted -->
  	<xsl:variable name="_target" select="doc($objId)/*/m:body/m:item[@id = $id]"/>
  	<xsl:if test="not($_target/m:rels[@group = 'main'])">
      <u:insert select=".">
        <rels id="{{new-id()}}" group="main"/>
      </u:insert>
    </xsl:if>
    <u:insert select="m:rels[@group = 'main']">
      <u:namespace prefix="m" uri="livcos.org/ns/map"/>
      <rel id="{{new-id()}}">
        <u:attribute name="ref">
          <xsl:text>#</xsl:text>
          <u:copy-of select="../../*[last()]/@id"/>
        </u:attribute>
      </rel>
    </u:insert>
  </xsl:template>
	
	<xsl:template match="m:rels" mode="insert">
		<xsl:copy copy-namespaces="no">
			<xsl:copy-of select="@*" copy-namespaces="no"/>
			<xsl:apply-templates select="m:rel" mode="#current"/>
			<xsl:if test="@group = 'sys'">
				<rel id="{{new-id()}}" ref="#{$id}"/>
			</xsl:if>
		</xsl:copy>
	</xsl:template>
	
	<xsl:template match="m:rel" mode="insert">
		<xsl:variable name="absRef">
			<xsl:if test="starts-with(@ref, '#')">
				<xsl:value-of select="../../../@object"/>
			</xsl:if>
			<xsl:value-of select="@ref"/>
		</xsl:variable>
		<xsl:copy copy-namespaces="no">
			<xsl:copy-of select="@id" copy-namespaces="no"/>
			<xsl:attribute name="ref">
				<xsl:choose>
					<xsl:when test="starts-with($absRef, concat($objId, '#'))">
						<xsl:value-of select="substring-after($absRef, $objId)"/>
					</xsl:when>
					<xsl:otherwise>
						<xsl:value-of select="$absRef"/>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:attribute>
		</xsl:copy>
	</xsl:template>
	
	<xsl:template match="m:rel" mode="backRef">
		<xsl:call-template name="insertBackRef">
			<xsl:with-param name="ref" select="@ref"/>
			<xsl:with-param name="srcObjId" select="../../../@object"/>
			<xsl:with-param name="srcId" select="../../@id"/>
			<xsl:with-param name="cut" select="../../../@type = 'cut'"/>
		</xsl:call-template>
	</xsl:template>
	
	<xsl:template name="insertBackRef">
		<xsl:param name="ref"/>
		<xsl:param name="srcObjId"/>
		<xsl:param name="srcId"/>
		<xsl:param name="cut"/>
		<xsl:param name="item"/>
		<xsl:variable name="absRef">
			<xsl:if test="starts-with($ref, '#')">
				<xsl:value-of select="$srcObjId"/>
			</xsl:if>
			<xsl:value-of select="$ref"/>
		</xsl:variable>
		<xsl:variable name="_objId" select="substring-before($absRef, '#')"/>
		<xsl:variable name="_objUri" select="concat($_objId, '.content')"/>
		<xsl:if test="doc-available($_objUri)">
			<xsl:variable name="_item" select="doc($_objUri)/*/m:body/m:item[@id = substring-after($absRef, '#')]"/>
			<xsl:variable name="_toSrcRef">
				<xsl:if test="$_objId != $srcObjId">
					<xsl:value-of select="$srcObjId"/>
				</xsl:if>
				<xsl:text>#</xsl:text>
				<xsl:value-of select="$srcId"/>
			</xsl:variable>
			<xsl:variable name="_rel" select="$_item/m:rels/m:rel[@ref = $_toSrcRef]"/>
			<xsl:if test="$_rel">
				<xsl:choose>
					<xsl:when test="$cut">
						<u:update ref="{$_objId}" scope="content" select="m:body/m:item/m:rels/m:rel[@id = '{$_rel/@id}']/@ref">
							<u:namespace prefix="m" uri="livcos.org/ns/map"/>
							<xsl:call-template name="buildRef">
								<xsl:with-param name="item" select="$item"/>
								<xsl:with-param name="targetObjId" select="$_objId"/>
							</xsl:call-template>
						</u:update>
					</xsl:when>
					<xsl:otherwise>
						<u:insert ref="{$_objId}" scope="content"
							select="m:body/m:item[@id ='{$_item/@id}']/m:rels[@group = '{$_rel/../@group}']">
							<u:namespace prefix="m" uri="livcos.org/ns/map"/>
							<rel id="{{new-id()}}">
								<u:attribute name="ref">
									<xsl:call-template name="buildRef">
										<xsl:with-param name="item" select="$item"/>
										<xsl:with-param name="targetObjId" select="$_objId"/>
									</xsl:call-template>
								</u:attribute>
							</rel>
						</u:insert>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:if>
		</xsl:if>
	</xsl:template>
	
	<xsl:template name="buildRef">
		<xsl:param name="item"/>
		<xsl:param name="targetObjId"/>
		<xsl:if test="$targetObjId != $objId">
			<xsl:value-of select="$objId"/>
		</xsl:if>
		<xsl:text>#</xsl:text>
		<xsl:choose>
			<xsl:when test="$item">
				<xsl:value-of select="$item/@id"/>
			</xsl:when>
			<xsl:otherwise>
				<u:copy-of ref="{$objId}" scope="content" select="*/*[last()]/@id"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	<xsl:template match="m:rel" mode="paste">
		<xsl:param name="into"/>
		<xsl:variable name="_target" select="doc($objId)/*//*[@id = $id]"/>
    <xsl:variable name="ref">
      <xsl:if test="starts-with(@ref,'#')">
        <xsl:value-of select="../@object"/>
      </xsl:if>
      <xsl:value-of select="@ref"/>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="local-name($_target) = 'item'">
        <xsl:call-template name="insertRel">
          <xsl:with-param name="ref" select="$ref"/>
          <xsl:with-param name="item" select="$_target"/>
        	<xsl:with-param name="entry" select=".."/>
        </xsl:call-template>
      </xsl:when>
    	<xsl:when test="(local-name($_target) = 'rel') and $into">
    		<xsl:variable name="_uri" select="f:cosmos-uri($_target/@ref, $_target)"/>
      	<xsl:variable name="_objUri" select="concat($_uri/obj, '.content')"/>
      	<xsl:if test="doc-available($_objUri)">
      		<u:context ref="{$_uri/obj}" scope="content">
      			<u:context select="*/*[@id = '{$_uri/id}']">
      				<xsl:call-template name="insertRel">
      					<xsl:with-param name="ref" select="$ref"/>
      					<xsl:with-param name="item" select="doc($_objUri)/*/m:body/m:item[@id = $_uri/id]"/>
      					<xsl:with-param name="entry" select=".."/>
      				</xsl:call-template>
      			</u:context>
      		</u:context>
      	</xsl:if>
    	</xsl:when>
    	<xsl:when test="local-name($_target) = 'rel'">
    		<xsl:apply-imports/>
    		<xsl:call-template name="insertBackRefForRel">
    			<xsl:with-param name="ref" select="$ref"/>
    			<xsl:with-param name="item" select="$_target/../.."/>
    			<xsl:with-param name="entry" select=".."/>
    		</xsl:call-template>
    	</xsl:when>
    </xsl:choose>
  </xsl:template>
  
  <xsl:template name="insertRel">
    <xsl:param name="ref"/>
    <xsl:param name="item"/>
  	<xsl:param name="entry"/>
    <xsl:variable name="_ref">
      <xsl:variable name="mapId" select="f:object-id($item)"/>
      <xsl:choose>
        <xsl:when test="starts-with($ref, concat($mapId, '#'))">
        	<xsl:text>#</xsl:text>
          <xsl:value-of select="substring-after($ref, '#')"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$ref"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
  	<xsl:if test="not($item/m:rels/m:rel[@ref = $_ref])">
    	<!-- insert the relation into the 'main' group -->
      <xsl:if test="not($item/m:rels[@group = 'main'])">
        <u:insert select=".">
          <rels id="{{new-id()}}" group="main"/>
        </u:insert>
      </xsl:if>
      <u:insert select="m:rels[@group = 'main']">
        <u:namespace prefix="m" uri="livcos.org/ns/map"/>
        <rel id="{@id}" ref="{$_ref}"/>
      </u:insert>
  	</xsl:if>
  	<xsl:call-template name="insertBackRefForRel">
  		<xsl:with-param name="ref" select="$ref"/>
  		<xsl:with-param name="item" select="$item"/>
  		<xsl:with-param name="entry" select="$entry"/>
  	</xsl:call-template>
  </xsl:template>
	
	<xsl:template name="insertBackRefForRel">
		<xsl:param name="ref"/>
		<xsl:param name="item"/>
		<xsl:param name="entry"/>
		<xsl:variable name="_srcObjUri" select="concat($entry/@object, '.content')"/>
  	<xsl:if test="doc-available($_srcObjUri)">
			<xsl:variable name="_srcRels" select="doc($_srcObjUri)/*/m:body/m:item/m:rels[@id = $entry/@parent]"/>
  		<xsl:if test="$_srcRels">
  			<xsl:call-template name="insertBackRef">
  				<xsl:with-param name="ref" select="$ref"/>
  				<xsl:with-param name="srcObjId" select="../@object"/>
  				<xsl:with-param name="srcId" select="$_srcRels/../@id"/>
  				<xsl:with-param name="cut" select="../@type = 'cut'"/>
  				<xsl:with-param name="item" select="$item"/>
  			</xsl:call-template>
  		</xsl:if>
  	</xsl:if>
  </xsl:template>
  
</xsl:stylesheet>